
// -扩展应用-对一定长度对数组进行计算（和统计）
// -随机生成数据 利用单线程与多线程做比较
 		// -这个比较既是最后的就结果
 		// -也是对于时间上的比价（单线程与多线程的比价-机器1核2G）

// 数组长度开始是10000

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h> // POSIX
#include<sys/time.h>
#include<time.h>
#include"../../util/tool.h"

// -单线程调用
long accmut(int * array,int arraySize){

    // -compare time
    struct timeval begin,last;
    gettimeofday(&begin,NULL);
    long sum = 0;
    for(int index = 0;index < arraySize;index++){

        sum+=array[index];
    }
    gettimeofday(&last,NULL);
    double spendTime = (last.tv_sec - begin.tv_sec) + 1e-6 * (last.tv_usec - begin.tv_usec);
    printf("spend time = %.7lf.\n",spendTime);
    return sum;
}

typedef struct{

    long sum;   // -单个线程计算除出来的值
    int minVal; // 最小范围[min,max]
    int maxVal; // 最大范围
    int * array;    //  数组 
    // int arraySize;  //  数组长度
}ThreadData;

#define THREAD_NUMBER 16

void * thread_accmut(void * arg){

    ThreadData * data = (ThreadData*)arg;
    data->sum = 0;
    for(int index = data->minVal;index<=data->maxVal;index++){

        data->sum += data->array[index];
    }
    return NULL;
}
// -prepare multip
long prepareThread(int * array,int length){

    ThreadData thdData[THREAD_NUMBER];
    pthread_t thdInfo[THREAD_NUMBER];

    int size = length/THREAD_NUMBER;
    int minVal = 0;
    int maxVal = size;
    // -最后一个的[min,max] 范围为 [0,16]
    for(int index = 0;index < THREAD_NUMBER-1;index++){

        thdData[index].sum = 0;
        thdData[index].array = array;
        // thdData[index].arraySize = length;
        thdData[index].minVal = minVal;
        thdData[index].maxVal = maxVal;

        minVal = maxVal + 1;
        maxVal += size;
    }
    thdData[THREAD_NUMBER-1].sum = 0;
    thdData[THREAD_NUMBER-1].array = array;
    thdData[THREAD_NUMBER-1].minVal = minVal;
    thdData[THREAD_NUMBER-1].maxVal = length-1; // -因为处理函数 所解决的范围为[min,max]
    // thdData[THREAD_NUMBER-1].arraySize = length;

    // -新建线程
    for(int index = 0;index < THREAD_NUMBER;index++){

        if(pthread_create(&thdInfo[index],NULL,thread_accmut,(void*)&thdData[index])!=0){

            printf("error happend.\n");
        }
    }
    // -统计和结束线程
    long sum = 0;
    for(int index = 0;index < THREAD_NUMBER;index++){

        pthread_join(thdInfo[index],NULL);
        sum += thdData[index].sum;
    }
    return sum;
}

int main(int argc,char * argv[]){

    long single = 0;
    long multiple = 0;

    int size = 10000;
    int * array = arrGen(size,NULL);
    switch (argc)
    {
    case 1:
        single = accmut(array,size);
        break;
    case 2:
        multiple = prepareThread(array,size);
        break;
    case 3:
        single = accmut(array,size);
        multiple = prepareThread(array,size);
        if(single == multiple){

            printf("is same.\n");
        }
        break;
    default:
        break;
    }
    printf("single sum = %ld and multiple sum = %ld.\n",single,multiple);
    return EXIT_SUCCESS;
}
